/*
 *  This file is part of Cube.
 *
 *  Cube is free software: you can redistribute it and/or modify
 *  it under the terms of the GNU General Public License as published by
 *  the Free Software Foundation, either version 3 of the License, or
 *  (at your option) any later version.
 *
 *  Cube is distributed in the hope that it will be useful,
 *  but WITHOUT ANY WARRANTY; without even the implied warranty of
 *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 *  GNU General Public License for more details.
 *
 *  You should have received a copy of the GNU General Public License
 *  along with Cube.  If not, see <http://www.gnu.org/licenses/>.
 *
 */

package cube.data;

import cube.CubeView;
import java.io.BufferedReader;
import java.io.File;
import java.io.FileNotFoundException;
import java.io.FileReader;
import java.io.FileWriter;
import java.io.IOException;
import java.util.ArrayList;
import javax.swing.JFileChooser;
import javax.swing.JFrame;
import javax.swing.filechooser.FileFilter;
import org.apache.log4j.Logger;

/**
 *
 * @author akermanl
 */
public class DataManager {
    
    private static DataManager instance;
    protected static final Logger log = Logger.getLogger(CubeView.class);
    private ArrayList<AccelerationDataVector> accelerationData = new ArrayList<AccelerationDataVector>();
    private CubeView cubeView;
    private boolean stopAcceleration = true;
    
    private DataManager(CubeView cubeView) {
        this.cubeView = cubeView;
    }
    
    public static DataManager getInstance (CubeView cubeView) {
         if (DataManager.instance == null) {
             DataManager.instance = new DataManager (cubeView);
         }
         return DataManager.instance;
    }
    
    public ArrayList<AccelerationDataVector> getAccelerationData() {
        return accelerationData;
    }
    
    public void addAccelerationDataVector(double x, double y, double z, double roll, double pitch) {
        if (this.stopAcceleration == false) {
            getAccelerationData().add(new AccelerationDataVector(x,y,z,roll,pitch));
            cubeView.updateChart(getAccelerationData());
            
        }
    }
    

    public AccelerationDataVector getAccelerationDataLast(){
        if (accelerationData.size()>0){
            return accelerationData.get(accelerationData.size()-1);        
        } else {
            return new AccelerationDataVector(0,0,0,0,0);
        }
    }
    
    
    public void processAccelerationData(double num_xlow, double num_xhigh,double num_ylow,double num_yhigh,double num_zlow,double num_zhigh){
        double numx,numy,numz,roll,pitch;
        numx=256*num_xhigh+num_xlow;
        if (numx>2048){
            numx=65536-numx;
        }else{
            numx=-numx;
        }
        numx=numx/1024;
        numy=256*num_yhigh+num_ylow;
        if (numy>2048){
            numy=65536-numy;
        }else{
            numy=-numy;
        }
        numy=numy/1024;
        numz=256*num_zhigh+num_zlow;
        if (numz>2048){
            numz=65536-numz;
        }else{
            numz=-numz;
        }
        numz=numz/1024;
        
        roll=Math.atan(numy/(numz));
        //roll=180/Math.PI*roll;
        pitch=Math.atan(-numx/numz);
        //pitch=180/Math.PI*pitch;
        
        //runden
        roll=(double)Math.round(roll*10)/10;
        pitch=(double)Math.round(pitch*10)/10;
        this.addAccelerationDataVector(numx, numy, numz, roll, pitch);
        //this.addAccelerationAngles(roll, pitch);
        log.debug("Receive data "+numx+" - "+numy+" - "+numz);
    }
    
    public void stopAcceleration(){
        this.stopAcceleration = true;
        log.debug("Stop recording data");
        
    }
    
    public void startAcceleration(){
        this.stopAcceleration = false;
        log.debug("Start recording data");
    }
    
    public void resetAcceleration(){
         this.accelerationData = new ArrayList<AccelerationDataVector>();
         //accelerationData.add(new AccelerationDataVector(0,0,0));  
         //chartManager.updateValues(getAccelerationData());
         
         log.debug("Recorded data deleted");
    }
    
         
    public void load(JFrame jFrame) {
        final JFileChooser fc = new JFileChooser();
        fc.addChoosableFileFilter(new FileFilter() {
            public boolean accept(File f) {
                if (f.isDirectory()) return true;
                return f.getName().toLowerCase().endsWith(".csv");
            }
            public String getDescription () { return "Comma Separated Values (.csv)"; }  
        });
        int returnVal = fc.showOpenDialog(jFrame);
        if (returnVal == JFileChooser.APPROVE_OPTION) {
            File file = fc.getSelectedFile();
            loadText(file);
        }
    }
    
    private void loadText(File file){
        StringBuffer buf = new StringBuffer();
        this.accelerationData = new ArrayList<AccelerationDataVector>();
        if(file.exists( )){            
            FileImport fileImport = new FileImport(file);
            fileImport.start();        
        }
    }
    
     class FileImport extends Thread {
       
       private File file;
       
       public FileImport(File file){
           super();
           this.file = file;
       }
       
      @Override public void run() { 
                        try{
                            BufferedReader reader = new BufferedReader(new FileReader(file));
                            String line = "";
                            boolean header = true;
                            while((line = reader.readLine( )) != null){
                                if (header == false) {                    
                                    String[] points = line.split( "\\;" ); 
                                    double numx = Double.parseDouble(points[0]);
                                    double numy = Double.parseDouble(points[1]);
                                    double numz = Double.parseDouble(points[2]);
                                    
                                    double roll=Math.atan(numy/(numz));
                                    roll=180/Math.PI*roll;
                                    double pitch=Math.atan(-numx/numz);
                                    pitch=180/Math.PI*pitch;
                                                                                                 
                                    getAccelerationData().add(new AccelerationDataVector(numx, numy, numz, roll, pitch));
                                    cubeView.updateChart(getAccelerationData());
                                   
                                } else {
                                    header = false;
                                }   
                                try {
                                        Thread.sleep( 1 ); //+- 75 Bilder/Sekunde 
                                }
                                catch ( InterruptedException e )  { 
                                    log.debug( "Interruption in animation" ); 
                                }
                            }
                            reader.close();
                            log.debug("Data import successful");
                       } catch (FileNotFoundException e) {
                            log.debug("File not found");
                        }
                        catch (IOException e) {
                            log.debug("Error occurred while importing data");
                         }
                    } 
    }
    
    public void save(JFrame jFrame) {
        final JFileChooser fc = new JFileChooser();
        fc.addChoosableFileFilter(new FileFilter() {
            public boolean accept(File f) {
                if (f.isDirectory()) return true;
                return f.getName().toLowerCase().endsWith(".csv");
            }
            public String getDescription () { return "Comma Separated Values (.csv)"; }  
        });
        int returnVal = fc.showSaveDialog(jFrame);
        if (returnVal == JFileChooser.APPROVE_OPTION) {
            File file = fc.getSelectedFile();
            saveText(file);
        }
    }
     
    private void saveText(File file) {
        try {
            FileWriter writer = new FileWriter(file);
            String text = "X;Y;Z\n";
            for (int i = 0; i < accelerationData.size(); i++) {
                text += accelerationData.get(i).getX()+";"+accelerationData.get(i).getY()+";"+accelerationData.get(i).getZ()+"\n";
            }
            writer.write(text);
            writer.flush( );
            writer.close( );
            log.debug("Data export successful");
            }
        catch (IOException e) {
            log.debug("Error occurred while exporting data");
            }
        }
}
